我們今天要來設定一個使者登錄註冊和身分驗證的系統,讓使用者可以註冊帳號,並能夠登入和登出
首先我們要先用startapp命令來建立名為users應用程式,如下python manage.py startapp users
然後我們可以看現在的learning_log目錄多了users的應用程式,也可以看users目錄裡面的結構跟learning_logs相同,如下
將users應用程式引入整個專案中,如下
INSTALLED_APPS = (
--省略--
'learning_logs',
'users', # 新增區塊
)
我們加了一行程式碼來引入users應用程式中的urls.py檔,這行程式碼與任何以users為開頭的URL都比對符合,如下
from django.urls import path, include
from django.contrib import admin
urlpatterns = [
path('admin/', admin.site.urls),
path('users/', include('users.urls')), # 新增區塊
path('', include('learning_logs.urls')),
]
我們現在要來做login的頁面,我們會在users資料夾裡面新增一個urls.py檔,如下
from django.conf.urls import url
from django.urls import path
from django.contrib.auth.views import LoginView
from . import views
app_name='users'
urlpatterns = [
path('login/', LoginView.as_view(template_name='users/login.html'), name="login"),
]
上面程式碼我們先在第三行匯入LoginView視圖,第九行是登入頁面的URL模式與URL http://localhost:8000/users/login 相配符合
使用者請求登入頁面時,Django會使用預設login視圖來處理,但我們還是需要為這個網頁提供模板,首先要在users資料夾裡建立一個templates資料夾,在templates資料夾中再建立一個users資料夾,裡面新增一個login.html,如下
{% extends "learning_logs/base.html" %}
{% block content %}
{% if form.errors %}
<p>Your username and password didn't match. Please try again.</p>
{% endif %}
<form method="post" action="{% url 'users:login' %}">
{% csrf_token %}
{{ form.as_p }}
<button name="submit">log in</button>
<input type="hidden" name="next"
value="{% url 'learning_logs:index' %}" />
</form>
{% endblock content %}
上面程式碼第五行是如果表單errors屬性被設定,就會顯示一條錯誤訊息,回報輸入的使用者名稱-密碼對與資料庫中儲存的都不相符,第十四行這裡放入一個隱藏的表單元素next,其中的引數會告知Django在使用者成功登入後會重新導向主頁
在base.html中新增連到login頁面的連結,如下
<p>
--省略--
{% if user.is_authenticated %}
Hello, {{ user.username }}.
{% else %}
<a href="{% url 'users:login' %}">log in</a>
{% endif %}
</p>
{% block content %}{% endblock %}
上面程式碼第三和第四行是如果使用者已登入就不會顯示連結
登入頁面如下
未登入使用者會先看到log in 連結
點進去後可以輸入使用者帳號和密碼
我們現在要來做的是登出,我們不用建立登出頁面,至要讓使用者按一個連結就可以登出並返回主頁
--省略--
urlpatterns = [
--省略--
path('logout/', views.logout_view, name='logout'),
]
匯入Django的logout()函式並呼叫它,再重新導向主頁,首先我們要開啟users資料夾中的views.py檔,如下
from django.shortcuts import render
from django.http import HttpResponseRedirect
from django.contrib.auth import logout # 匯入logout函式
from django.urls import reverse
def logout_view(request): # 呼叫logout函式,它會把request當作引數,然後重新導向主頁
logout(request)
return HttpResponseRedirect(reverse('learning_logs:index'))
在base.html中新增連到logout的連結,如下
<p>
--省略--
{% if user.is_authenticated %}
Hello, {{ user.username }}.
<a href="{% url 'users:logout' %}">log out</a>
{% else %}
--省略--
{% endif %}
</p>
{% block content %}{% endblock %}
將第五行的logout連結放在if區塊內是因為只有在使用者登入時才能看到logout連結
登出連結如下
這裡要建立讓使用者可以登錄註冊的頁面,我們會使用Django預設提供的UserCreationForm表單
--省略--
urlpatterns = [
--省略--
path('register/', views.register, name='register'),
]
在登入註冊頁面第一次被請求時,register視圖函是需要顯是一個空的物註冊表單,並在使用者填好資料提交表單時對它進行處理,如果登入註冊成功,這個函式還需要讓使用者登入系統,現在我們要開啟views.py檔來新增一些程式碼,如下
from django.shortcuts import render
from django.http import HttpResponseRedirect
from django.contrib.auth import logout
from django.urls import reverse
from django.contrib.auth.forms import UserCreationForm
--省略--
def register(request):
"""Register a new user."""
if request.method != 'POST':
form = UserCreationForm()
else:
form = UserCreationForm(data=request.POST)
if form.is_valid():
new_user = form.save()
authenticated_user = authenticate(username=new_user.username,
password=request.POST['password1'])
login(request, authenticated_user)
return HttpResponseRedirect(reverse('learning_logs:index'))
context = {'form': form}
return render(request, 'users/register.html', context)
新增一個register.html檔放在和login.html同一個資料夾,如下
{% extends "learning_logs/base.html" %}
{% block content %}
<form method="post" action="{% url 'users:register' %}">
{% csrf_token %}
{{ form.as_p }}
<button name="submit">register</button>
<input type="hidden" name="next" value="{% url 'learning_logs:index' %}" />
</form>
{% endblock content %}
在base.html中新增連到登入頁面的連結,如下
<p>
--省略--
{% else %}
<a href="{% url 'users:register' %}">register</a> -
--省略--
{% endif %}
</p>
{% block content %}{% endblock %}
登入註冊連結如下
會看到主頁多了register連結
點進來後會看到預設的表單
附上排版較精美的
HackMD網址:https://hackmd.io/k4M00PB4TDKybC0IAJtCQw?both
資料來源:<<python程式設計的樂趣>>-Eric Matthes著/H&C譯
資料來源:https://stackoverflow.com/questions/51906428/django-cannot-import-login-from-django-contrib-auth-views/51906537
資料來源:https://github.com/ehmatthes/pcc/tree/master/chapter_19#p-439-including-the-urls-from-users